<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LoRA管理器</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: #1a1a1a;
            color: #ffffff;
            overflow-x: hidden;
        }

        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            padding: 20px;
            box-shadow: 0 4px 20px rgba(102, 126, 234, 0.3);
        }

        .header-content {
            max-width: 1200px;
            margin: 0 auto;
            display: flex;
            justify-content: space-between;
            align-items: center;
        }

        .header h1 {
            font-size: 24px;
            font-weight: bold;
            margin-bottom: 8px;
        }

        .header .subtitle {
            font-size: 14px;
            opacity: 0.8;
        }

        .nav {
            display: flex;
            gap: 20px;
        }

        .nav-item {
            color: white;
            text-decoration: none;
            padding: 8px 16px;
            border-radius: 6px;
            transition: all 0.3s ease;
        }

        .nav-item:hover {
            background: rgba(255, 255, 255, 0.2);
        }

        .nav-item.active {
            background: rgba(255, 255, 255, 0.3);
        }

        .controls {
            padding: 20px;
            background: #2a2a2a;
            border-bottom: 1px solid #333;
        }

        .search-container {
            display: flex;
            flex-direction: column;
            gap: 12px;
            margin-bottom: 16px;
        }

        .search-input {
            flex: 1;
            padding: 12px 16px;
            background: #333;
            border: 1px solid #555;
            border-radius: 8px;
            color: white;
            font-size: 14px;
        }

        .filter-inputs {
            display: flex;
            gap: 12px;
        }

        .filter-input {
            flex: 1;
            padding: 10px 14px;
            background: #333;
            border: 1px solid #555;
            border-radius: 6px;
            color: white;
            font-size: 13px;
        }

        .filter-input::placeholder {
            color: #888;
        }

        .search-input:focus {
            outline: none;
            border-color: #667eea;
            box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.2);
        }

        .filter-buttons {
            display: flex;
            gap: 8px;
        }

        .filter-btn {
            padding: 8px 16px;
            background: #333;
            border: 1px solid #555;
            border-radius: 6px;
            color: white;
            cursor: pointer;
            font-size: 12px;
            transition: all 0.3s ease;
        }

        .filter-btn.active {
            background: #667eea;
            border-color: #667eea;
        }

        .filter-btn:hover {
            background: #444;
        }

        .sort-container {
            display: flex;
            align-items: center;
            gap: 12px;
            margin-top: 12px;
            padding: 12px;
            background: #2a2a2a;
            border-radius: 8px;
        }

        .sort-label {
            color: #ccc;
            font-size: 14px;
            font-weight: 500;
        }

        .sort-btn {
            display: flex;
            align-items: center;
            gap: 6px;
            padding: 8px 12px;
            background: #333;
            border: 1px solid #555;
            border-radius: 6px;
            color: white;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 14px;
        }

        .sort-btn:hover {
            background: #444;
        }

        .sort-btn.active {
            background: #667eea;
            border-color: #667eea;
        }

        .sort-icon {
            font-size: 16px;
        }

        .lora-grid {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
            gap: 20px;
            padding: 20px;
            align-items: start;
        }

        .lora-card {
            background: #2a2a2a;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            transition: all 0.3s ease;
            border: 1px solid #333;
            display: flex;
            flex-direction: column;
            height: 100%;
            min-height: 200px;
        }

        .lora-card:hover {
            transform: translateY(-4px);
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
            border-color: #667eea;
        }

        /* 图片查看模态框样式 - 全屏 */
        .image-modal-content {
            width: 95vw;
            height: 95vh;
            max-width: 95vw;
            max-height: 95vh;
            margin: 2.5vh auto;
            border-radius: 12px;
            background: #1a1a1a;
            display: flex;
            flex-direction: column;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.8);
        }

        .image-gallery {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
            gap: 20px;
            padding: 30px;
            height: calc(95vh - 120px);
            overflow-y: auto;
            flex: 1;
        }

        .gallery-item {
            position: relative;
            background: #2a2a2a;
            border-radius: 12px;
            overflow: hidden;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
            border: 1px solid #444;
            min-height: 200px;
            display: flex;
            flex-direction: column;
        }

        .gallery-item:hover {
            transform: scale(1.02);
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
            border-color: #667eea;
        }

        .image-container {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            padding: 10px;
            min-height: 200px;
        }

        .gallery-item img {
            width: 100%;
            height: auto;
            object-fit: contain;
            max-height: 300px;
            background: #1a1a1a;
            border-radius: 8px;
        }

        .image-overlay {
            position: absolute;
            bottom: 0;
            left: 0;
            right: 0;
            background: linear-gradient(transparent, rgba(0, 0, 0, 0.9));
            color: white;
            padding: 15px;
            opacity: 0;
            transition: opacity 0.3s ease;
        }

        .gallery-item:hover .image-overlay {
            opacity: 1;
        }

        .image-info {
            text-align: center;
        }

        .image-title {
            font-size: 14px;
            font-weight: bold;
            margin-bottom: 5px;
        }

        .image-action {
            font-size: 12px;
            opacity: 0.8;
        }

        .empty-gallery {
            text-align: center;
            padding: 40px;
            color: #888;
        }

        .empty-icon {
            font-size: 48px;
            margin-bottom: 16px;
        }

        .empty-text {
            font-size: 16px;
        }

        /* 全屏图片查看器 */
        .fullscreen-modal {
            background: rgba(0, 0, 0, 0.95);
            z-index: 10000;
        }

        .fullscreen-content {
            position: relative;
            width: 100vw;
            height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .fullscreen-image {
            max-width: 90vw;
            max-height: 90vh;
            object-fit: contain;
        }

        .close-fullscreen {
            position: absolute;
            top: 20px;
            right: 20px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            border: none;
            font-size: 24px;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            cursor: pointer;
            z-index: 10001;
        }

        .image-counter {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 8px 16px;
            border-radius: 20px;
            font-size: 14px;
        }

        .lora-image {
            width: 100%;
            height: 200px;
            background: #333;
            display: flex;
            align-items: center;
            justify-content: center;
            color: #666;
            font-size: 14px;
            position: relative;
            overflow: hidden;
        }

        .lora-image img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .lora-image-placeholder {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 8px;
        }

        .lora-content {
            padding: 16px;
        }

        .lora-name {
            font-size: 16px;
            font-weight: bold;
            margin-bottom: 8px;
            color: #ffffff;
        }

        .lora-path {
            font-size: 12px;
            color: #888;
            margin-bottom: 8px;
            word-break: break-all;
        }

        .lora-tags {
            display: flex;
            flex-wrap: wrap;
            gap: 4px;
            margin-bottom: 12px;
        }

        .lora-tag {
            background: #667eea;
            color: white;
            padding: 2px 8px;
            border-radius: 12px;
            font-size: 10px;
            font-weight: bold;
        }

        .lora-description {
            font-size: 12px;
            color: #ccc;
            margin-bottom: 12px;
            line-height: 1.4;
        }

        .lora-actions {
            display: flex;
            gap: 8px;
        }

        .action-btn {
            flex: 1;
            padding: 8px 12px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 12px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .use-btn {
            background: #4CAF50;
            color: white;
        }

        .use-btn:hover {
            background: #45a049;
        }

        .edit-btn {
            background: #FF9800;
            color: white;
        }

        .edit-btn:hover {
            background: #f57c00;
        }

        .favorite-btn {
            background: #333;
            color: white;
            border: 1px solid #555;
        }

        .favorite-btn:hover {
            background: #444;
        }

        .favorite-btn.favorited {
            background: #e91e63;
            border-color: #e91e63;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            z-index: 1000;
        }

        .modal-content {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            background: #2a2a2a;
            border-radius: 12px;
            padding: 24px;
            width: 90%;
            max-width: 600px;
            max-height: 80vh;
            overflow-y: auto;
            z-index: 1001;
        }

        .modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
        }

        .modal-title {
            font-size: 20px;
            font-weight: bold;
        }

        .close-btn {
            background: none;
            border: none;
            color: #888;
            font-size: 24px;
            cursor: pointer;
        }

        .form-group {
            margin-bottom: 16px;
        }

        .form-label {
            display: block;
            margin-bottom: 8px;
            font-weight: bold;
            color: #ffffff;
        }

        .form-input {
            width: 100%;
            padding: 12px;
            background: #333;
            border: 1px solid #555;
            border-radius: 6px;
            color: white;
            font-size: 14px;
        }

        .form-input:focus {
            outline: none;
            border-color: #667eea;
        }

        .form-textarea {
            min-height: 80px;
            resize: vertical;
        }

        .image-upload {
            border: 2px dashed #555;
            border-radius: 8px;
            padding: 20px;
            text-align: center;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .image-upload:hover {
            border-color: #667eea;
            background: rgba(102, 126, 234, 0.1);
        }

        .image-preview {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
            gap: 12px;
            margin-top: 12px;
        }

        .image-item {
            position: relative;
            aspect-ratio: 1;
            border-radius: 8px;
            overflow: hidden;
        }

        .image-item img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .image-remove {
            position: absolute;
            top: 4px;
            right: 4px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            border: none;
            border-radius: 50%;
            width: 24px;
            height: 24px;
            cursor: pointer;
            font-size: 12px;
        }

        .modal-actions {
            display: flex;
            gap: 12px;
            justify-content: flex-end;
            margin-top: 24px;
        }

        /* 图片弹窗样式 */
        .image-modal-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.8);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 10000;
        }

        .image-modal-content {
            background: #2a2a2a;
            border-radius: 12px;
            max-width: 90vw;
            max-height: 90vh;
            overflow: hidden;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.5);
        }

        .image-modal-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 20px;
            border-bottom: 1px solid #444;
        }

        .image-modal-header h3 {
            font-size: 18px;
            font-weight: bold;
            margin: 0;
        }

        .image-modal-header .close-btn {
            background: none;
            border: none;
            color: #999;
            font-size: 24px;
            cursor: pointer;
            padding: 0;
            width: 30px;
            height: 30px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .image-modal-header .close-btn:hover {
            color: #fff;
        }

        .image-modal-body {
            padding: 20px;
            max-height: 80vh;
            overflow-y: auto;
            display: flex;
            gap: 20px;
        }

        .image-display {
            flex: 1;
            text-align: center;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .prompt-info {
            flex: 0 0 300px;
            max-height: 80vh;
            overflow-y: auto;
            background: #333;
            border-radius: 8px;
            padding: 16px;
        }

        .prompt-info h4 {
            font-size: 16px;
            margin-bottom: 12px;
            color: #667eea;
        }

        .prompt-text {
            background: #1a1a1a;
            padding: 12px;
            border-radius: 6px;
            font-family: 'Courier New', monospace;
            font-size: 14px;
            line-height: 1.5;
            white-space: pre-wrap;
            word-break: break-word;
        }

        .no-prompt {
            color: #999;
            font-style: italic;
            text-align: center;
            padding: 20px;
        }


        .btn {
            padding: 12px 24px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-size: 14px;
            font-weight: bold;
            transition: all 0.3s ease;
        }

        .btn-primary {
            background: #667eea;
            color: white;
        }

        .btn-primary:hover {
            background: #5a6fd8;
        }

        .btn-secondary {
            background: #333;
            color: white;
            border: 1px solid #555;
        }

        .btn-secondary:hover {
            background: #444;
        }

        .loading {
            text-align: center;
            padding: 40px;
            color: #888;
        }

        .empty-state {
            text-align: center;
            padding: 60px 20px;
            color: #666;
        }

        .empty-state h3 {
            margin-bottom: 12px;
            color: #888;
        }

        .empty-state p {
            margin-bottom: 20px;
        }

        .sync-btn {
            background: #4CAF50;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 6px;
            cursor: pointer;
            font-size: 12px;
            font-weight: bold;
        }

        .sync-btn:hover {
            background: #45a049;
        }

        .sync-btn:disabled {
            background: #666;
            cursor: not-allowed;
        }

        @media (max-width: 768px) {
            .lora-grid {
                grid-template-columns: 1fr;
                padding: 12px;
            }
            
            .search-container {
                flex-direction: column;
            }
            
            .filter-buttons {
                justify-content: center;
            }
        }

        /* 图片浏览模态框样式 */
        .image-gallery-modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.9);
            z-index: 10000;
            display: flex;
            flex-direction: column;
        }

        .gallery-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15px 20px;
            background: #2a2a2a;
            border-bottom: 1px solid #444;
        }

        .gallery-header h3 {
            color: #fff;
            font-size: 18px;
            margin: 0;
        }

        .gallery-close {
            color: #fff;
            font-size: 24px;
            cursor: pointer;
            padding: 5px;
            line-height: 1;
        }

        .gallery-close:hover {
            background: #444;
            border-radius: 3px;
        }

        .gallery-container {
            flex: 1;
            display: flex;
            height: calc(100vh - 60px);
        }

        .thumbnail-sidebar {
            width: 150px;
            background: #1a1a1a;
            border-right: 1px solid #444;
            overflow-y: auto;
            padding: 10px;
        }

        .thumbnail-list {
            display: flex;
            flex-direction: column;
            gap: 10px;
        }

        .thumbnail-item {
            cursor: pointer;
            border: 2px solid transparent;
            border-radius: 5px;
            overflow: hidden;
            transition: all 0.3s ease;
        }

        .thumbnail-item:hover {
            border-color: #667eea;
        }

        .thumbnail-item.active {
            border-color: #667eea;
            box-shadow: 0 0 10px rgba(102, 126, 234, 0.5);
        }

        .thumbnail-item img {
            width: 100%;
            height: auto;
            min-height: 80px;
            max-height: 120px;
            object-fit: contain;
            display: block;
            background: #333;
        }

        .main-image-area {
            flex: 1;
            display: flex;
            align-items: center;
            justify-content: center;
            position: relative;
            background: #000;
        }

        .nav-btn {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background: rgba(102, 126, 234, 0.8);
            color: white;
            border: none;
            width: 50px;
            height: 50px;
            border-radius: 50%;
            font-size: 24px;
            cursor: pointer;
            z-index: 10;
            transition: all 0.3s ease;
        }

        .nav-btn:hover {
            background: rgba(102, 126, 234, 1);
            transform: translateY(-50%) scale(1.1);
        }

        .prev-btn {
            left: 20px;
        }

        .next-btn {
            right: 20px;
        }

        .image-display {
            position: relative;
            max-width: 100%;
            max-height: 100%;
            display: flex;
            flex-direction: column;
            align-items: center;
        }

        .main-image {
            max-width: 100%;
            height: 100vh;
            object-fit: contain;
            border-radius: 5px;
            cursor: grab;
            transition: transform 0.3s ease;
        }
        
        .main-image:active {
            cursor: grabbing;
        }
        
        .main-image.zoom-mode {
            cursor: zoom-in;
        }
        
        .main-image.zoom-mode.zoomed {
            cursor: zoom-out;
        }
        
        .main-image.zoomed {
            transform: scale(1.5);
        }
        
        /* 模式切换按钮 */
        .mode-controls {
            position: absolute;
            top: 20px;
            right: 20px;
            z-index: 1000;
            display: flex;
            gap: 10px;
        }
        
        .mode-btn {
            padding: 8px 16px;
            background: rgba(0,0,0,0.7);
            color: white;
            border: 1px solid #666;
            border-radius: 4px;
            cursor: pointer;
            font-size: 12px;
            transition: all 0.3s ease;
        }
        
        .mode-btn:hover {
            background: rgba(0,0,0,0.9);
            border-color: #4285f4;
        }
        
        .mode-btn.active {
            background: #4285f4;
            border-color: #4285f4;
        }
        
        /* 缩放和拖拽模式 */
        .image-display.manual-mode {
            overflow: hidden;
        }
        
        .image-display.manual-mode .main-image {
            cursor: zoom-in;
        }
        
        .image-display.manual-mode .main-image.zoomed {
            cursor: zoom-out;
        }

        .image-info {
            position: absolute;
            bottom: 20px;
            left: 50%;
            transform: translateX(-50%);
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 8px 16px;
            border-radius: 20px;
            font-size: 14px;
        }

        .prompt-info-sidebar {
            width: 300px;
            background: #1a1a1a;
            border-left: 1px solid #444;
            padding: 20px;
            overflow-y: auto;
        }

        .prompt-info-sidebar h4 {
            color: #fff;
            margin-bottom: 15px;
            font-size: 16px;
        }

        .lora-info {
            color: #ccc;
            line-height: 1.6;
        }

        .lora-info div {
            margin-bottom: 10px;
        }

        .lora-info strong {
            color: #667eea;
        }

        .prompt-info {
            margin-top: 10px;
        }

        .prompt-text {
            background: #2a2a2a;
            padding: 15px;
            border-radius: 8px;
            color: #fff;
            line-height: 1.6;
            max-height: 200px;
            overflow-y: auto;
            margin-bottom: 10px;
            border: 1px solid #444;
        }

        .copy-btn {
            background: #667eea;
            color: white;
            border: none;
            padding: 8px 16px;
            border-radius: 5px;
            cursor: pointer;
            font-size: 14px;
            transition: all 0.3s ease;
            width: 100%;
        }

        .copy-btn:hover {
            background: #5a6fd8;
            transform: translateY(-1px);
        }

        .copy-btn:active {
            transform: translateY(0);
        }
    </style>
</head>
<body>
    <div class="header">
        <div class="header-content">
            <div>
                <h1>🎯 LoRA管理器</h1>
                <div class="subtitle">管理您的LoRA模型库</div>
            </div>
            <nav class="nav">
                <a href="/xhh/manager/index.html" class="nav-item">首页</a>
                <a href="/xhh/prompt-manager" class="nav-item">提示词管理</a>
                <a href="/xhh/lora-manager" class="nav-item active">LoRA管理</a>
                <a href="/xhh/manager/categories.html" class="nav-item">基础分类</a>
            </nav>
        </div>
    </div>

    <div class="controls">
        <div class="search-container">
            <input type="text" class="search-input" placeholder="搜索LoRA名称、标签或描述..." id="searchInput">
            <div class="filter-inputs">
                <input type="text" class="filter-input" placeholder="包含 (include) - 逗号分隔，支持正则表达式" id="includeInput">
                <input type="text" class="filter-input" placeholder="排除 (exclude) - 逗号分隔，支持正则表达式" id="excludeInput">
            </div>
            <button class="sync-btn" id="syncBtn">🔄 同步本地LoRA</button>
        </div>
        <div class="filter-buttons">
            <button class="filter-btn active" data-filter="all">全部</button>
            <button class="filter-btn" data-filter="character">角色</button>
            <button class="filter-btn" data-filter="tool">工具</button>
            <button class="filter-btn" data-filter="style">风格</button>
            <button class="filter-btn" data-filter="favorite">收藏</button>
        </div>
        
        <div class="sort-container">
            <span class="sort-label">排序:</span>
            <button class="sort-btn active" data-sort="usage" data-order="desc">
                <span class="sort-icon">📊</span>
                使用数量
            </button>
            <button class="sort-btn" data-sort="name" data-order="asc">
                <span class="sort-icon">🔤</span>
                名称
            </button>
        </div>
    </div>

    <div class="lora-grid" id="loraGrid">
        <div class="loading">正在加载LoRA列表...</div>
    </div>

    <!-- 编辑模态框 -->
    <div class="modal" id="editModal">
        <div class="modal-content">
            <div class="modal-header">
                <h2 class="modal-title">编辑LoRA信息</h2>
                <button class="close-btn" onclick="loraManager.closeEditModal()">&times;</button>
            </div>
            <form id="editForm">
                <div class="form-group">
                    <label class="form-label">LoRA名称</label>
                    <input type="text" class="form-input" id="loraName" required>
                </div>
                <div class="form-group">
                    <label class="form-label">标签</label>
                    <input type="text" class="form-input" id="loraTags" placeholder="用逗号分隔多个标签">
                </div>
                <div class="form-group">
                    <label class="form-label">描述</label>
                    <textarea class="form-input form-textarea" id="loraDescription" placeholder="描述这个LoRA的用途和特点"></textarea>
                </div>
                <div class="form-group">
                    <label class="form-label">触发词</label>
                    <input type="text" class="form-input" id="loraTrigger" placeholder="LoRA的触发词">
                </div>
                <div class="form-group">
                    <label class="form-label">提示词示例</label>
                    <textarea class="form-input form-textarea" id="loraPrompt" placeholder="使用这个LoRA的提示词示例"></textarea>
                </div>
                <div class="form-group">
                    <label class="form-label">示例图片</label>
                    <div class="image-upload" onclick="document.getElementById('imageInput').click()">
                        <div>点击上传图片</div>
                        <div style="font-size: 12px; color: #888; margin-top: 4px;">支持多张图片</div>
                    </div>
                    <input type="file" id="imageInput" multiple accept="image/*" style="display: none;">
                    <div class="image-preview" id="imagePreview"></div>
                </div>
                <div class="modal-actions">
                    <button type="button" class="btn btn-secondary" onclick="loraManager.closeEditModal()">取消</button>
                    <button type="submit" class="btn btn-primary">保存</button>
                </div>
            </form>
        </div>
    </div>

    <script>
        class LoraManager {
            constructor() {
                this.loras = [];
                this.filteredLoras = [];
                this.currentFilter = 'all';
                this.searchQuery = '';
                this.includeQuery = '';
                this.excludeQuery = '';
                this.editingLora = null;
                this.images = [];
                
                this.init();
            }

            async init() {
                console.log("🎯 LoRA管理器初始化");
                this.setupEventListeners();
                await this.loadLoras();
            }

            setupEventListeners() {
                // 搜索功能
                document.getElementById('searchInput').addEventListener('input', (e) => {
                    this.searchQuery = e.target.value.toLowerCase();
                    this.filterLoras();
                });

                // Include/Exclude过滤
                document.getElementById('includeInput').addEventListener('input', (e) => {
                    this.includeQuery = e.target.value;
                    this.filterLoras();
                });

                document.getElementById('excludeInput').addEventListener('input', (e) => {
                    this.excludeQuery = e.target.value;
                    this.filterLoras();
                });

                // 过滤按钮
                document.querySelectorAll('.filter-btn').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        document.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
                        e.target.classList.add('active');
                        this.currentFilter = e.target.dataset.filter;
                        this.filterLoras();
                    });
                });

                // 同步按钮
                document.getElementById('syncBtn').addEventListener('click', () => {
                    this.syncLocalLoras();
                });

                // 排序按钮
                document.querySelectorAll('.sort-btn').forEach(btn => {
                    btn.addEventListener('click', (e) => {
                        // 移除所有排序按钮的active状态
                        document.querySelectorAll('.sort-btn').forEach(b => b.classList.remove('active'));
                        // 添加当前按钮的active状态
                        e.target.classList.add('active');
                        
                        // 获取排序参数
                        const sortBy = e.target.dataset.sort;
                        const sortOrder = e.target.dataset.order;
                        
                        console.log("🎯 排序参数:", sortBy, sortOrder);
                        
                        // 执行排序
                        this.sortLoras(sortBy, sortOrder);
                    });
                });

                // 编辑表单
                document.getElementById('editForm').addEventListener('submit', (e) => {
                    e.preventDefault();
                    this.saveLora();
                });

                // 图片上传
                document.getElementById('imageInput').addEventListener('change', (e) => {
                    this.handleImageUpload(e.target.files);
                });
            }

            async loadLoras() {
                try {
                    console.log("🎯 加载LoRA列表");
                    
                    // 获取URL参数
                    const urlParams = new URLSearchParams(window.location.search);
                    const includeParam = urlParams.get('include') || '';
                    const excludeParam = urlParams.get('exclude') || '';
                    
                    console.log("🎯 URL参数 - include:", includeParam, "exclude:", excludeParam);
                    
                    // 如果有URL参数，设置到输入框中
                    if (includeParam) {
                        const includeInput = document.getElementById('includeInput');
                        if (includeInput) {
                            // 将多行格式转换为逗号分隔格式
                            const includeValue = includeParam.replace(/\n/g, ', ');
                            includeInput.value = includeValue;
                            this.includeQuery = includeValue;
                        }
                    }
                    
                    if (excludeParam) {
                        const excludeInput = document.getElementById('excludeInput');
                        if (excludeInput) {
                            // 将多行格式转换为逗号分隔格式
                            const excludeValue = excludeParam.replace(/\n/g, ', ');
                            excludeInput.value = excludeValue;
                            this.excludeQuery = excludeValue;
                        }
                    }
                    
                    const response = await fetch('/api/xhh/lora-list');
                    const data = await response.json();
                    
                    console.log("🎯 API返回数据:", data);
                    
                    if (data.success) {
                        this.loras = data.data || [];
                        console.log("🎯 加载到LoRA数量:", this.loras.length);
                        this.filterLoras();
                    } else {
                        console.error("❌ 加载LoRA列表失败:", data.message);
                        this.showError("加载LoRA列表失败");
                    }
                } catch (error) {
                    console.error("❌ 加载LoRA列表错误:", error);
                    this.showError("加载LoRA列表时发生错误");
                }
            }

            filterLoras() {
                console.log("🎯 过滤LoRA列表");
                
                this.filteredLoras = this.loras.filter(lora => {
                    // 搜索过滤
                    if (this.searchQuery) {
                        const searchText = `${lora.name} ${lora.tags || ''} ${lora.description || ''}`.toLowerCase();
                        if (!searchText.includes(this.searchQuery)) {
                            return false;
                        }
                    }

                    // Include过滤 (正则表达式) - 主要针对lora_path
                    if (this.includeQuery.trim()) {
                        const includePatterns = this.includeQuery.split(',').map(p => p.trim()).filter(p => p);
                        let matchesInclude = false;
                        for (const pattern of includePatterns) {
                            try {
                                const regex = new RegExp(pattern, 'i');
                                // 优先匹配路径，然后匹配名称、标签、描述
                                if (regex.test(lora.path) || 
                                    regex.test(lora.name) || 
                                    (lora.tags && lora.tags.some(tag => regex.test(tag))) ||
                                    (lora.description && regex.test(lora.description))) {
                                    matchesInclude = true;
                                    break;
                                }
                            } catch (e) {
                                // 如果正则表达式无效，使用普通字符串匹配
                                const text = `${lora.path} ${lora.name} ${lora.tags || ''} ${lora.description || ''}`.toLowerCase();
                                if (text.includes(pattern.toLowerCase())) {
                                    matchesInclude = true;
                                    break;
                                }
                            }
                        }
                        if (!matchesInclude) {
                            return false;
                        }
                    }

                    // Exclude过滤 (正则表达式) - 主要针对lora_path
                    if (this.excludeQuery.trim()) {
                        const excludePatterns = this.excludeQuery.split(',').map(p => p.trim()).filter(p => p);
                        for (const pattern of excludePatterns) {
                            try {
                                const regex = new RegExp(pattern, 'i');
                                // 优先匹配路径，然后匹配名称、标签、描述
                                if (regex.test(lora.path) || 
                                    regex.test(lora.name) || 
                                    (lora.tags && lora.tags.some(tag => regex.test(tag))) ||
                                    (lora.description && regex.test(lora.description))) {
                                    return false;
                                }
                            } catch (e) {
                                // 如果正则表达式无效，使用普通字符串匹配
                                const text = `${lora.path} ${lora.name} ${lora.tags || ''} ${lora.description || ''}`.toLowerCase();
                                if (text.includes(pattern.toLowerCase())) {
                                    return false;
                                }
                            }
                        }
                    }

                    // 标签过滤
                    if (this.currentFilter !== 'all') {
                        if (this.currentFilter === 'favorite') {
                            if (!lora.is_favorite) {
                                return false;
                            }
                        } else {
                            if (!lora.tags || !lora.tags.includes(this.currentFilter)) {
                                return false;
                            }
                        }
                    }

                    return true;
                });

                this.renderLoras();
            }

            sortLoras(sortBy, sortOrder) {
                console.log("🎯 排序LoRA列表:", sortBy, sortOrder);
                
                this.filteredLoras.sort((a, b) => {
                    let valueA, valueB;
                    
                    if (sortBy === 'name') {
                        // 按名称排序
                        valueA = a.name || '';
                        valueB = b.name || '';
                    } else if (sortBy === 'usage') {
                        // 按使用数量排序（关联图片数量）
                        valueA = a.image_list ? JSON.parse(a.image_list).length : 0;
                        valueB = b.image_list ? JSON.parse(b.image_list).length : 0;
                    } else {
                        return 0;
                    }
                    
                    // 处理字符串比较
                    if (typeof valueA === 'string' && typeof valueB === 'string') {
                        valueA = valueA.toLowerCase();
                        valueB = valueB.toLowerCase();
                    }
                    
                    let result = 0;
                    if (valueA < valueB) {
                        result = -1;
                    } else if (valueA > valueB) {
                        result = 1;
                    }
                    
                    // 根据排序顺序调整结果
                    return sortOrder === 'desc' ? -result : result;
                });
                
                console.log("🎯 排序完成，重新渲染");
                this.renderLoras();
            }

            renderLoras() {
                const grid = document.getElementById('loraGrid');
                
                console.log("🎯 渲染LoRA列表，数量:", this.filteredLoras.length);
                
                if (this.filteredLoras.length === 0) {
                    grid.innerHTML = `
                        <div class="empty-state">
                            <h3>没有找到LoRA</h3>
                            <p>尝试调整搜索条件或同步本地LoRA</p>
                            <button class="sync-btn" onclick="loraManager.syncLocalLoras()">🔄 同步本地LoRA</button>
                        </div>
                    `;
                    return;
                }

                grid.innerHTML = this.filteredLoras.map(lora => {
                    console.log("🎯 渲染LoRA:", lora);
                    return `
                        <div class="lora-card" data-id="${lora.id}" onclick="loraManager.viewLoraImages('${lora.id}')">
                            <div class="lora-image">
                                ${lora.images && lora.images.length > 0 ? 
                                    `<img src="${lora.images[0]}" alt="${lora.name}" onerror="loraManager.handleImageError(this)">` :
                                    `<div class="lora-image-placeholder">
                                        <div>🖼️</div>
                                        <div>无图片</div>
                                    </div>`
                                }
                            </div>
                            <div class="lora-content">
                                <div class="lora-name">${this.escapeHtml(lora.name)}</div>
                                <div class="lora-path">${this.escapeHtml(lora.path)}</div>
                                <div class="lora-tags">
                                    ${(lora.tags || []).map(tag => `<span class="lora-tag">${this.escapeHtml(tag)}</span>`).join('')}
                                </div>
                                <div class="lora-description">${this.escapeHtml(lora.description || '')}</div>
                                <div class="lora-actions">
                                    <button class="action-btn use-btn" onclick="event.stopPropagation(); loraManager.useLora('${lora.id}')">使用</button>
                                    <button class="action-btn edit-btn" onclick="event.stopPropagation(); loraManager.editLora('${lora.id}')">编辑</button>
                                    <button class="action-btn favorite-btn ${lora.is_favorite ? 'favorited' : ''}" onclick="event.stopPropagation(); loraManager.toggleFavorite('${lora.id}')">
                                        ${lora.is_favorite ? '❤️' : '🤍'}
                                    </button>
                                </div>
                            </div>
                        </div>
                    `;
                }).join('');
            }

            useLora(loraId) {
                const lora = this.loras.find(l => l.id === loraId);
                if (lora) {
                    console.log("🎯 使用LoRA:", lora);
                    
                    // 发送消息给父窗口
                    window.parent.postMessage({
                        type: 'use_lora',
                        lora_path: lora.path,
                        lora_name: lora.name
                    }, '*');
                }
            }

            viewLoraImages(loraId) {
                const lora = this.loras.find(l => l.id === loraId);
                if (lora) {
                    console.log("🎯 查看LoRA图片:", lora.name);
                    this.openImageModal(lora);
                }
            }

            openImageModal(lora) {
                // 创建图片查看模态框
                const modal = document.createElement('div');
                modal.className = 'modal';
                modal.id = 'imageModal';
                modal.innerHTML = `
                    <div class="modal-content image-modal-content">
                        <div class="modal-header">
                            <h2 class="modal-title">${this.escapeHtml(lora.name)} - 关联图片</h2>
                            <button class="close-btn" onclick="loraManager.closeImageModal()">&times;</button>
                        </div>
                        <div class="image-gallery" id="imageGallery">
                            ${this.renderImageGallery(lora.images || [], lora.id)}
                        </div>
                        <div class="modal-footer">
                            <button class="action-btn" onclick="loraManager.closeImageModal()">关闭</button>
                        </div>
                    </div>
                `;
                
                document.body.appendChild(modal);
                modal.style.display = 'block';
                
                // 点击背景关闭
                modal.onclick = (event) => {
                    if (event.target === modal) {
                        modal.remove();
                    }
                };
                
                // ESC键关闭
                const handleKeyDown = (event) => {
                    if (event.key === 'Escape') {
                        modal.remove();
                        document.removeEventListener('keydown', handleKeyDown);
                    }
                };
                document.addEventListener('keydown', handleKeyDown);
            }

            renderImageGallery(images, loraId = null) {
                console.log("🔍 renderImageGallery 调用:");
                console.log("  - images:", images);
                console.log("  - loraId:", loraId, "类型:", typeof loraId);
                
                if (!images || images.length === 0) {
                    return `
                        <div class="empty-gallery">
                            <div class="empty-icon">🖼️</div>
                            <div class="empty-text">暂无关联图片</div>
                        </div>
                    `;
                }

                return images.map((image, index) => `
                    <div class="gallery-item" onclick="loraManager.openOriginalImage('${image.replace(/'/g, "\\'")}', '${loraId || 'null'}')">
                        <div class="image-container">
                            <img src="${image}" alt="图片 ${index + 1}" onerror="loraManager.handleImageError(this)">
                        </div>
                        <div class="image-overlay">
                            <div class="image-info">
                                <div class="image-title">图片 ${index + 1}</div>
                                <div class="image-action">点击查看原图</div>
                            </div>
                        </div>
                    </div>
                `).join('');
            }

            viewFullImage(imageUrl, index) {
                // 创建全屏图片查看器
                const fullscreenModal = document.createElement('div');
                fullscreenModal.className = 'modal fullscreen-modal';
                fullscreenModal.innerHTML = `
                    <div class="fullscreen-content">
                        <button class="close-fullscreen" onclick="loraManager.closeFullscreenModal()">&times;</button>
                        <img src="${imageUrl}" alt="全屏图片" class="fullscreen-image">
                        <div class="image-counter">${index + 1} / ${document.querySelectorAll('.gallery-item').length}</div>
                    </div>
                `;
                
                document.body.appendChild(fullscreenModal);
                fullscreenModal.style.display = 'block';
                
                // 点击背景关闭
                fullscreenModal.onclick = (event) => {
                    if (event.target === fullscreenModal) {
                        fullscreenModal.remove();
                    }
                };
                
                // ESC键关闭
                const handleKeyDown = (event) => {
                    if (event.key === 'Escape') {
                        fullscreenModal.remove();
                        document.removeEventListener('keydown', handleKeyDown);
                    }
                };
                document.addEventListener('keydown', handleKeyDown);
            }

            closeImageModal() {
                const modal = document.getElementById('imageModal');
                if (modal) {
                    modal.remove();
                }
            }

            closeFullscreenModal() {
                const modal = document.querySelector('.fullscreen-modal');
                if (modal) {
                    modal.remove();
                }
            }

            async openOriginalImage(imageUrl, loraId = null) {
                console.log("🎯 打开原始图片:");
                console.log("  - imageUrl:", imageUrl);
                console.log("  - loraId:", loraId, "类型:", typeof loraId);
                console.log("  - loraId === 'null':", loraId === 'null');
                console.log("  - loraId === null:", loraId === null);
                
                // 从loraId获取loraName
                let loraName = null;
                if (loraId && loraId !== 'null') {
                    const lora = this.loras.find(l => l.id === loraId);
                    if (lora) {
                        loraName = lora.name;
                        console.log("  - 找到的LoRA名称:", loraName);
                    }
                }
                
                if (loraName) {
                    // 如果有loraName，通过API获取图片列表
                    console.log("🎯 通过API获取图片列表，loraName:", loraName);
                    try {
                        const response = await fetch(`/api/xhh/lora-images?lora_name=${encodeURIComponent(loraName)}`);
                        const result = await response.json();
                        console.log("🎯 API响应:", result);
                        
                        if (result.success && result.data && result.data.images) {
                            const apiImages = result.data.images;
                            console.log("🎯 从API获取的图片列表:", apiImages);
                            this.showLoraImageGalleryWithImages(imageUrl, apiImages, loraId, loraName);
                        } else {
                            console.log("🎯 API未返回图片，使用原有逻辑");
                            this.showImageModal(imageUrl, loraId, loraName);
                        }
                    } catch (error) {
                        console.error("🎯 API请求失败:", error);
                        this.showImageModal(imageUrl, loraId, loraName);
                    }
                } else {
                    console.log("🎯 没有loraName，使用原有逻辑");
                    this.showImageModal(imageUrl, loraId, loraName);
                }
            }
            
            showLoraImageGalleryWithImages(imageUrl, images, loraId = null, loraName = null) {
                console.log("🎯 直接使用图片列表显示图片浏览界面");
                console.log("  - imageUrl:", imageUrl);
                console.log("  - images:", images);
                console.log("  - loraId:", loraId);
                console.log("  - loraName:", loraName);
                
                if (!images || images.length === 0) {
                    console.log('该LoRA没有图片');
                    return;
                }
                
                // 找到当前图片在列表中的索引
                this.currentImageIndex = images.findIndex(img => img === imageUrl);
                if (this.currentImageIndex === -1) this.currentImageIndex = 0;
                
                this.currentImages = images;
                this.currentLoraId = loraId;
                
                this.showLoraImageGallery();
            }
            
            async showImageModal(imageUrl, loraId = null, loraName = null) {
                try {
                    // 获取LoRA的所有图片
                    const images = await this.getLoraImages(loraId, loraName);
                    if (images.length === 0) {
                        console.log('该LoRA没有图片');
                        return;
                    }
                    
                    this.currentImageIndex = images.findIndex(img => img === imageUrl);
                    if (this.currentImageIndex === -1) this.currentImageIndex = 0;
                    
                    this.currentImages = images;
                    this.currentLoraId = loraId;
                    
                    this.showLoraImageGallery();
                    
                } catch (error) {
                    console.error("❌ 显示图片弹窗失败:", error);
                    // 如果出错，回退到直接打开
                    window.open(imageUrl, '_blank');
                }
            }
            
            async getLoraImages(loraId, loraName = null) {
                console.log("🔍 getLoraImages 调用:");
                console.log("  - loraId:", loraId, "类型:", typeof loraId);
                console.log("  - loraName:", loraName, "类型:", typeof loraName);
                console.log("  - loraId === 'null':", loraId === 'null');
                console.log("  - loraId === null:", loraId === null);
                console.log("  - !loraId:", !loraId);
                
                if (!loraId || loraId === 'null') {
                    // 如果没有指定LoRA ID，返回所有LoRA的图片
                    const allImages = [];
                    this.loras.forEach(lora => {
                        if (lora.image_list) {
                            try {
                                const images = JSON.parse(lora.image_list);
                                if (Array.isArray(images)) {
                                    allImages.push(...images);
                                }
                            } catch (e) {
                                console.error('解析LoRA图片列表失败:', e);
                            }
                        }
                    });
                    return [...new Set(allImages)]; // 去重
                }
                
                console.log("🔍 当前LoRA列表中的ID类型和值:");
                this.loras.forEach((lora, index) => {
                    console.log(`  - LoRA ${index}: id=${lora.id} (${typeof lora.id}), name=${lora.name}`);
                });
                
                // 从当前LoRA数据中获取图片
                // 首先尝试通过ID查找，如果失败则通过名称查找
                let lora = this.loras.find(l => l.id == loraId);
                if (!lora && loraName) {
                    console.log("🔍 通过ID没找到，尝试通过名称查找:", loraName);
                    lora = this.loras.find(l => l.name === loraName);
                }
                
                console.log("🔍 查找LoRA结果:");
                console.log("  - 查找条件: l.id == loraId 或 l.name === loraName");
                console.log("  - loraId:", loraId);
                console.log("  - loraName:", loraName);
                console.log("  - 找到的LoRA:", lora);
                
                if (lora && lora.image_list) {
                    try {
                        const images = JSON.parse(lora.image_list);
                        console.log("🔍 解析的图片列表:", images);
                        return Array.isArray(images) ? images : [];
                    } catch (e) {
                        console.error('解析LoRA图片列表失败:', e);
                        return [];
                    }
                }
                
                return [];
            }
            
            showLoraImageGallery() {
                // 创建图片浏览模态框
                const modal = document.createElement('div');
                modal.className = 'image-gallery-modal';
                modal.innerHTML = `
                    <div class="gallery-header">
                        <h3 id="galleryTitle">LoRA图片浏览</h3>
                        <span class="gallery-close" id="galleryClose">&times;</span>
                    </div>
                    <div class="gallery-container">
                        <!-- 左侧缩略图列表 -->
                        <div class="thumbnail-sidebar">
                            <div class="thumbnail-list" id="thumbnailList">
                                <!-- 缩略图将在这里动态生成 -->
                            </div>
                        </div>
                        
                        <!-- 中间主图片区域 -->
                        <div class="main-image-area">
                            <button class="nav-btn prev-btn" id="prevBtn">‹</button>
                            <div class="image-display" id="loraImageDisplay">
                                <img id="mainImage" class="main-image" src="" alt="">
                                <div class="image-info">
                                    <span id="imageCounter">1 / 1</span>
                                </div>
                                <!-- 模式切换按钮 -->
                                <div class="mode-controls">
                                    <button class="mode-btn active" id="scrollModeBtn" onclick="loraManager.setMode('scroll')">滚动模式</button>
                                    <button class="mode-btn" id="manualModeBtn" onclick="loraManager.setMode('manual')">手动模式</button>
                                </div>
                            </div>
                            <button class="nav-btn next-btn" id="nextBtn">›</button>
                        </div>
                        
                        <!-- 右侧LoRA信息和提示词 -->
                        <div class="prompt-info-sidebar">
                            <h4>LoRA信息</h4>
                            <div id="loraInfo" class="lora-info"></div>
                            
                            <h4 style="margin-top: 20px;">当前图片提示词</h4>
                            <div id="currentPromptInfo" class="prompt-info">
                                <div class="prompt-text" id="currentPromptText">暂无提示词信息</div>
                                <button class="copy-btn" id="copyPromptBtn" onclick="loraManager.copyPrompt()">复制提示词</button>
                            </div>
                        </div>
                    </div>
                `;
                
                // 添加到页面
                document.body.appendChild(modal);
                
                // 生成缩略图列表
                const thumbnailList = document.getElementById('thumbnailList');
                thumbnailList.innerHTML = this.currentImages.map((img, index) => `
                    <div class="thumbnail-item ${index === this.currentImageIndex ? 'active' : ''}" 
                         data-index="${index}" onclick="loraManager.goToImage(${index})">
                        <img src="${img}" alt="缩略图 ${index + 1}">
                    </div>
                `).join('');
                
                // 显示当前图片
                this.updateMainImage();
                
                // 更新LoRA信息
                if (this.currentLoraId) {
                    const lora = this.loras.find(l => l.id == this.currentLoraId);
                    if (lora) {
                        const loraInfo = document.getElementById('loraInfo');
                        loraInfo.innerHTML = `
                            <div><strong>名称:</strong> ${lora.name}</div>
                            <div><strong>路径:</strong> ${lora.path}</div>
                            <div><strong>描述:</strong> ${lora.description || '无'}</div>
                            <div><strong>标签:</strong> ${lora.tags || '无'}</div>
                        `;
                    }
                }
                
                // 绑定事件
                this.bindLoraGalleryEvents(modal);
                
                // 初始化图片交互事件
                setTimeout(() => {
                    this.initLoraImageInteractions();
                }, 100);
            }
            
            updateMainImage() {
                const mainImage = document.getElementById('mainImage');
                const imageCounter = document.getElementById('imageCounter');
                const currentImage = this.currentImages[this.currentImageIndex];
                
                if (mainImage && imageCounter) {
                    mainImage.src = currentImage;
                    imageCounter.textContent = `${this.currentImageIndex + 1} / ${this.currentImages.length}`;
                    
                    // 更新缩略图选中状态
                    document.querySelectorAll('.thumbnail-item').forEach((item, index) => {
                        item.classList.toggle('active', index === this.currentImageIndex);
                    });
                    
                    // 更新提示词信息
                    this.updatePromptInfo(currentImage);
                }
            }
            
            async updatePromptInfo(imageUrl) {
                try {
                    const response = await fetch(`/api/xhh/image-prompt-info?image=${encodeURIComponent(imageUrl)}`);
                    const result = await response.json();
                    
                    const promptText = document.getElementById('currentPromptText');
                    const copyBtn = document.getElementById('copyPromptBtn');
                    
                    if (result.success && result.data && result.data.text) {
                        promptText.textContent = result.data.text;
                        copyBtn.style.display = 'block';
                    } else {
                        promptText.textContent = '暂无提示词信息';
                        copyBtn.style.display = 'none';
                    }
                } catch (error) {
                    console.error('获取提示词信息失败:', error);
                    const promptText = document.getElementById('currentPromptText');
                    promptText.textContent = '获取提示词信息失败';
                }
            }
            
            copyPrompt() {
                const promptText = document.getElementById('currentPromptText');
                const text = promptText.textContent;
                
                if (text && text !== '暂无提示词信息' && text !== '获取提示词信息失败') {
                    navigator.clipboard.writeText(text).then(() => {
                        // 显示复制成功提示
                        const copyBtn = document.getElementById('copyPromptBtn');
                        const originalText = copyBtn.textContent;
                        copyBtn.textContent = '已复制!';
                        copyBtn.style.background = '#28a745';
                        
                        setTimeout(() => {
                            copyBtn.textContent = originalText;
                            copyBtn.style.background = '#667eea';
                        }, 2000);
                    }).catch(err => {
                        console.error('复制失败:', err);
                        alert('复制失败，请手动复制');
                    });
                }
            }
            
            goToImage(index) {
                if (index >= 0 && index < this.currentImages.length) {
                    this.currentImageIndex = index;
                    this.updateMainImage();
                }
            }
            
            // 设置LoRA图片浏览模式
            setMode(mode) {
                const imageDisplay = document.getElementById('loraImageDisplay');
                const mainImage = document.getElementById('mainImage');
                const scrollBtn = document.getElementById('scrollModeBtn');
                const manualBtn = document.getElementById('manualModeBtn');
                
                // 更新按钮状态
                scrollBtn.classList.toggle('active', mode === 'scroll');
                manualBtn.classList.toggle('active', mode === 'manual');
                
                // 更新显示模式
                imageDisplay.classList.toggle('manual-mode', mode === 'manual');
                
                if (mode === 'scroll') {
                    // 滚动模式：恢复默认状态
                    mainImage.classList.remove('zoomed');
                    mainImage.style.transform = '';
                    mainImage.style.cursor = 'grab';
                } else {
                    // 手动模式：启用缩放和拖拽
                    mainImage.style.cursor = 'zoom-in';
                }
                
                console.log(`🔄 LoRA切换到${mode === 'scroll' ? '滚动' : '手动'}模式`);
            }
            
            // 初始化LoRA图片交互事件
            initLoraImageInteractions() {
                const mainImage = document.getElementById('mainImage');
                const imageDisplay = document.getElementById('loraImageDisplay');
                
                if (!mainImage || !imageDisplay) return;
                
                let isZoomed = false;
                let isDragging = false;
                let startX = 0;
                let startY = 0;
                let translateX = 0;
                let translateY = 0;
                
                // 点击切换缩放
                mainImage.addEventListener('click', (e) => {
                    if (imageDisplay.classList.contains('manual-mode')) {
                        e.preventDefault();
                        isZoomed = !isZoomed;
                        mainImage.classList.toggle('zoomed', isZoomed);
                        mainImage.style.cursor = isZoomed ? 'zoom-out' : 'zoom-in';
                        
                        if (!isZoomed) {
                            // 重置位置
                            mainImage.style.transform = '';
                            translateX = 0;
                            translateY = 0;
                        }
                    }
                });
                
                // 拖拽功能
                mainImage.addEventListener('mousedown', (e) => {
                    if (imageDisplay.classList.contains('manual-mode') && isZoomed) {
                        e.preventDefault();
                        isDragging = true;
                        startX = e.clientX - translateX;
                        startY = e.clientY - translateY;
                        mainImage.style.cursor = 'grabbing';
                    }
                });
                
                document.addEventListener('mousemove', (e) => {
                    if (isDragging && isZoomed) {
                        e.preventDefault();
                        translateX = e.clientX - startX;
                        translateY = e.clientY - startY;
                        mainImage.style.transform = `scale(1.5) translate(${translateX}px, ${translateY}px)`;
                    }
                });
                
                document.addEventListener('mouseup', () => {
                    if (isDragging) {
                        isDragging = false;
                        mainImage.style.cursor = isZoomed ? 'zoom-out' : 'zoom-in';
                    }
                });
                
                // 鼠标滚轮控制 - 滚动模式切换图片，手动模式缩放
                imageDisplay.addEventListener('wheel', (e) => {
                    e.preventDefault();
                    
                    if (imageDisplay.classList.contains('manual-mode')) {
                        // 手动模式：缩放图片
                        const delta = e.deltaY > 0 ? 0.9 : 1.1;
                        const currentScale = isZoomed ? 1.5 : 1;
                        const newScale = Math.max(0.5, Math.min(3, currentScale * delta));
                        
                        if (newScale > 1.1) {
                            isZoomed = true;
                            mainImage.classList.add('zoomed');
                            mainImage.style.cursor = 'zoom-out';
                        } else {
                            isZoomed = false;
                            mainImage.classList.remove('zoomed');
                            mainImage.style.cursor = 'zoom-in';
                            translateX = 0;
                            translateY = 0;
                        }
                        
                        mainImage.style.transform = `scale(${newScale}) translate(${translateX}px, ${translateY}px)`;
                    } else {
                        // 滚动模式：切换图片
                        if (e.deltaY > 0) {
                            // 向下滚动，下一张图片
                            this.nextImage();
                        } else {
                            // 向上滚动，上一张图片
                            this.prevImage();
                        }
                    }
                });
            }
            
            nextImage() {
                this.currentImageIndex = (this.currentImageIndex + 1) % this.currentImages.length;
                this.updateMainImage();
            }
            
            prevImage() {
                this.currentImageIndex = (this.currentImageIndex - 1 + this.currentImages.length) % this.currentImages.length;
                this.updateMainImage();
            }
            
            bindLoraGalleryEvents(modal) {
                const closeBtn = document.getElementById('galleryClose');
                const prevBtn = document.getElementById('prevBtn');
                const nextBtn = document.getElementById('nextBtn');
                const thumbnailList = document.getElementById('thumbnailList');
                
                // 关闭按钮
                closeBtn.onclick = () => {
                    modal.remove();
                };
                
                // 点击背景关闭
                modal.onclick = (event) => {
                    if (event.target === modal) {
                        modal.remove();
                    }
                };
                
                // ESC键关闭
                const handleKeyDown = (event) => {
                    if (event.key === 'Escape') {
                        modal.remove();
                        document.removeEventListener('keydown', handleKeyDown);
                    }
                };
                document.addEventListener('keydown', handleKeyDown);
                
                // 导航按钮
                prevBtn.onclick = () => this.prevImage();
                nextBtn.onclick = () => this.nextImage();
                
                // 键盘导航
                const keyHandler = (event) => {
                    if (modal.parentNode) {
                        if (event.key === 'ArrowLeft') {
                            this.prevImage();
                        } else if (event.key === 'ArrowRight') {
                            this.nextImage();
                        } else if (event.key === 'Escape') {
                            modal.remove();
                            document.removeEventListener('keydown', keyHandler);
                        }
                    }
                };
                document.addEventListener('keydown', keyHandler);
                
                // 鼠标滚轮控制缩略图
                if (thumbnailList) {
                    thumbnailList.addEventListener('wheel', (event) => {
                        event.preventDefault();
                        const delta = event.deltaY > 0 ? 1 : -1;
                        const newIndex = Math.max(0, Math.min(this.currentImages.length - 1, this.currentImageIndex + delta));
                        if (newIndex !== this.currentImageIndex) {
                            this.goToImage(newIndex);
                        }
                    });
                }
            }
            
            async getImagePromptInfo(imageUrl) {
                try {
                    // 从图片URL中提取文件名
                    const fileName = imageUrl.split('/').pop();
                    
                    // 调用API获取图片的提示词信息
                    const response = await fetch(`/api/xhh/image-prompt-info?image=${encodeURIComponent(fileName)}`);
                    const data = await response.json();
                    
                    if (data.success && data.prompt) {
                        return data.prompt;
                    }
                    
                    return null;
                } catch (error) {
                    console.error("❌ 获取图片提示词信息失败:", error);
                    return null;
                }
            }

            handleImageError(imgElement) {
                // 处理图片加载错误
                console.log("🎯 图片加载失败，显示占位符");
                imgElement.parentElement.innerHTML = `
                    <div class="lora-image-placeholder">
                        <div>🖼️</div>
                        <div>无图片</div>
                    </div>
                `;
            }

            editLora(loraId) {
                console.log("🎯 编辑LoRA:", loraId);
                const lora = this.loras.find(l => l.id === loraId);
                console.log("🎯 找到LoRA:", lora);
                if (lora) {
                    this.editingLora = lora;
                    this.openEditModal();
                } else {
                    console.error("❌ 未找到LoRA:", loraId);
                }
            }

            openEditModal() {
                const modal = document.getElementById('editModal');
                const form = document.getElementById('editForm');
                
                // 填充表单
                document.getElementById('loraName').value = this.editingLora.name || '';
                document.getElementById('loraTags').value = (this.editingLora.tags || []).join(', ');
                document.getElementById('loraDescription').value = this.editingLora.description || '';
                document.getElementById('loraTrigger').value = this.editingLora.trigger || '';
                document.getElementById('loraPrompt').value = this.editingLora.prompt || '';
                
                // 显示现有图片
                this.images = [...(this.editingLora.images || [])];
                this.renderImagePreview();
                
                modal.style.display = 'block';
            }

            closeEditModal() {
                document.getElementById('editModal').style.display = 'none';
                this.editingLora = null;
                this.images = [];
            }

            async saveLora() {
                try {
                    const formData = new FormData();
                    formData.append('id', this.editingLora.id);
                    formData.append('name', document.getElementById('loraName').value);
                    formData.append('tags', document.getElementById('loraTags').value);
                    formData.append('description', document.getElementById('loraDescription').value);
                    formData.append('trigger', document.getElementById('loraTrigger').value);
                    formData.append('prompt', document.getElementById('loraPrompt').value);
                    formData.append('images', JSON.stringify(this.images));

                    const response = await fetch('/api/xhh/lora-save', {
                        method: 'POST',
                        body: formData
                    });

                    const result = await response.json();
                    
                    if (result.success) {
                        console.log("🎯 LoRA保存成功");
                        this.closeEditModal();
                        await this.loadLoras();
                    } else {
                        console.error("❌ LoRA保存失败:", result.message);
                        this.showError("保存LoRA失败");
                    }
                } catch (error) {
                    console.error("❌ 保存LoRA错误:", error);
                    this.showError("保存LoRA时发生错误");
                }
            }

            async handleImageUpload(files) {
                console.log("🎯 开始上传图片到提示词管理系统");
                
                for (const file of Array.from(files)) {
                    if (file.type.startsWith('image/')) {
                        try {
                            // 使用提示词管理系统的图片上传接口
                            const formData = new FormData();
                            formData.append('image', file);
                            
                            const response = await fetch('/api/xhh/upload-image', {
                                method: 'POST',
                                body: formData
                            });
                            
                            const result = await response.json();
                            
                            if (result.success) {
                                // 获取上传后的图片URL
                                const imageUrl = result.image_url || result.url;
                                this.images.push(imageUrl);
                                console.log("🎯 图片上传成功:", imageUrl);
                            } else {
                                console.error("❌ 图片上传失败:", result.message);
                                this.showError(`图片上传失败: ${result.message}`);
                            }
                        } catch (error) {
                            console.error("❌ 图片上传错误:", error);
                            this.showError("图片上传时发生错误");
                        }
                    }
                }
                
                this.renderImagePreview();
            }

            renderImagePreview() {
                const preview = document.getElementById('imagePreview');
                preview.innerHTML = this.images.map((image, index) => `
                    <div class="image-item">
                        <img src="${image}" alt="预览">
                        <button class="image-remove" onclick="loraManager.removeImage(${index})">&times;</button>
                    </div>
                `).join('');
            }

            removeImage(index) {
                this.images.splice(index, 1);
                this.renderImagePreview();
            }

            toggleFavorite(loraId) {
                const lora = this.loras.find(l => l.id === loraId);
                if (lora) {
                    lora.is_favorite = !lora.is_favorite;
                    this.renderLoras();
                }
            }

            async syncLocalLoras() {
                const syncBtn = document.getElementById('syncBtn');
                syncBtn.disabled = true;
                syncBtn.textContent = '🔄 同步中...';
                
                try {
                    console.log("🎯 开始手动同步LoRA");
                    
                    // 首先获取本地LoRA文件列表
                    const loraList = await this.getLocalLoraFiles();
                    console.log("🎯 找到本地LoRA文件:", loraList.length, "个");
                    
                    if (loraList.length === 0) {
                        console.log("🎯 没有找到本地LoRA文件");
                        this.showError("没有找到本地LoRA文件");
                        return;
                    }
                    
                    // 调用新的手动同步接口
                    const response = await fetch('/api/xhh/sync-loras', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify({
                            loras: loraList
                        })
                    });
                    
                    const result = await response.json();
                    
                    if (result.success) {
                        console.log("🎯 LoRA同步成功:", result);
                        const message = `同步完成！新增: ${result.synced_count} 个，更新: ${result.updated_count} 个，总计处理: ${result.total_processed} 个`;
                        console.log("🎯", message);
                        this.showSuccess(message);
                        await this.loadLoras();
                    } else {
                        console.error("❌ LoRA同步失败:", result.error);
                        this.showError(`同步LoRA失败: ${result.error}`);
                    }
                } catch (error) {
                    console.error("❌ 同步LoRA错误:", error);
                    this.showError("同步LoRA时发生错误");
                } finally {
                    syncBtn.disabled = false;
                    syncBtn.textContent = '🔄 同步本地LoRA';
                }
            }
            
            async getLocalLoraFiles() {
                try {
                    // 调用API获取本地LoRA文件列表
                    const response = await fetch('/api/xhh/lora-files');
                    const result = await response.json();
                    
                    if (result.success && result.files) {
                        return result.files.map(file => ({
                            path: file.path,
                            name: file.name || file.path.split(/[/\\]/).pop().replace(/\.(safetensors|pt)$/, '')
                        }));
                    } else {
                        console.error("❌ 获取本地LoRA文件失败:", result.error);
                        return [];
                    }
                } catch (error) {
                    console.error("❌ 获取本地LoRA文件错误:", error);
                    return [];
                }
            }

            escapeHtml(text) {
                const div = document.createElement('div');
                div.textContent = text;
                return div.innerHTML;
            }

            showError(message) {
                console.error("❌ 错误:", message);
                // 可以在这里添加错误提示UI
                alert(`错误: ${message}`);
            }
            
            showSuccess(message) {
                console.log("✅ 成功:", message);
                // 可以在这里添加成功提示UI
                alert(`成功: ${message}`);
            }
        }

        // 初始化LoRA管理器
        const loraManager = new LoraManager();
    </script>
</body>
</html>
